﻿using System.Data.Common;
using Abp.Zero.EntityFramework;
using FutureApp.Authorization.Roles;
using FutureApp.MultiTenancy;
using FutureApp.Users;
using System.Data.Entity;
using FutureApp.Configuration;
using System.Reflection;
using System.Linq;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace FutureApp.EntityFramework
{
    public class FutureAppDbContext : AbpZeroDbContext<Tenant, Role, User>
    {
        //TODO: Define an IDbSet for your Entities...
        #region IDbSetForEntities(System)

        public IDbSet<Navigation.Menu> Menus { get; set; }

        public IDbSet<Authorization.Permissions.PermissionDefinition> PermissionDefinitions { get; set; }

        #endregion

        #region IDbSetForEntities(Goods)

        public IDbSet<Shop.Goods> Goods { get; set; }

        public IDbSet<Shop.GoodsPrice> GoodsPrices { get; set; }

        public IDbSet<Shop.GoodsStock> GoodsStocks { get; set; }

        public IDbSet<Shop.GoodsStockTransaction> GoodsStockTransactions { get; set; }

        public IDbSet<Shop.GoodsAttribute> GoodsAttributes { get; set; }

        public IDbSet<Shop.GoodsAttributeValue> GoodsAttributeValues { get; set; }

        public IDbSet<Shop.GoodsAttributeDistribution> GoodsAttributeDistributions { get; set; }

        public IDbSet<Shop.GoodsBrand> Brands { get; set; }

        public IDbSet<xl.GoodsBrandTest> BrandsTest { get; set; }

        public IDbSet<Shop.GoodsCategory> Categories { get; set; }

        public IDbSet<Shop.GoodsCategoryAssemble> CategoryAssembles { get; set; }

        public IDbSet<Shop.GoodsItem> Items { get; set; }

        public IDbSet<Shop.GoodsMould> GoodsMoulds { get; set; }

        public IDbSet<Shop.GoodsMouldAssemble> GoodsMouldAssembles { get; set; }

        public IDbSet<Shop.GoodsProperty> GoodsProperties { get; set; }

        public IDbSet<Shop.GoodsPropertyValue> GoodsPropertyValues { get; set; }

        public IDbSet<Shop.GoodsPropertyDistribution> GoodsPropertyDistributions { get; set; }


        public IDbSet<xl.DTest> DTest { get; set; }

        public IDbSet<xl.MTest> MTest { get; set; }

      
        #endregion

        #region IDbSetForEntities(Person)

        public IDbSet<Person.Student> Student{ get; set; }

        public IDbSet<Person.Type> Type { get; set; }

        public IDbSet<Person.Bag> Bag { get; set; }

        public IDbSet<Person.Course> Course { get; set; }

        public IDbSet<Person.Choose> Choose { get; set; }

        #endregion
        #region IDbSetForEntities(Orders)

        public IDbSet<Orders.OrderHead> OrderHead { get; set; }

        public IDbSet<Orders.OrderMain> OrderMain { get; set; }

        public IDbSet<Orders.Stage> Stage { get; set; }

        #endregion


        #region IDbSetForEntities(Media)

        public IDbSet<Media.File> Files { get; set; }

        public IDbSet<Media.Picture> Pictures { get; set; }

        public IDbSet<Media.Video> Videos { get; set; }

        public IDbSet<Media.Voice> Voices { get; set; }

        #endregion

        #region IDbSetForEntities(Cms)

        public IDbSet<Cms.Article> Articles { get; set; }

        public IDbSet<Cms.Message> Messages { get; set; }

        #endregion

        #region ChangeTableName

        private static string TablePrefix = SettingsManager.GetAppSetting("website:DbPrefix");

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.ChangeAbpTablePrefix<Tenant, Role, User>(TablePrefix);

            //移除级联删除
            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
            modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

            #region 修改定义表的前缀
            var changePrefixTableFunc = typeof(FutureAppDbModelBuilderExtensions).GetMethod("ChangePrefixTable", BindingFlags.Public | BindingFlags.Static);

            this.GetType()
                .GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
                .Where(prop => prop.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>))
                .SelectMany(prop => prop.PropertyType.GetGenericArguments())
                .ToList()
                .ForEach(type => changePrefixTableFunc.MakeGenericMethod(type).Invoke(null, new object[] { modelBuilder, TablePrefix, null }));
            #endregion

            //Decimal小数位
            modelBuilder.Conventions.Add<DecimalPrecisionAttributeConvention>();
        }

        #endregion

        #region Constructors

        /* NOTE: 
         *   Setting "Default" to base class helps us when working migration commands on Package Manager Console.
         *   But it may cause problems when working Migrate.exe of EF. If you will apply migrations on command line, do not
         *   pass connection string name to base classes. ABP works either way.
         */
        public FutureAppDbContext()
            : this(SettingsManager.GetAppSetting("website:ConnectionStringName"))
        {

        }

        /* NOTE:
         *   This constructor is used by ABP to pass connection string defined in FutureAppDataModule.PreInitialize.
         *   Notice that, actually you will not directly create an instance of FutureAppDbContext since ABP automatically handles it.
         */
        public FutureAppDbContext(string nameOrConnectionString)
            : base(nameOrConnectionString)
        {

        }

        //This constructor is used in tests
        public FutureAppDbContext(DbConnection connection)
            : base(connection, true)
        {

        }

        #endregion       
    }
}
